package com.caocaog.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.caocaog.market.entity.GoodsBase;
import com.caocaog.market.entity.dto.GoodsDTO;
import com.caocaog.market.entity.dto.GoodsSpecDTO;
import com.caocaog.market.entity.vo.GoodsVO;
import com.caocaog.market.mapper.GoodsBaseMapper;
import com.caocaog.market.mapper.ShopCartDuplicateMapper;
import com.caocaog.market.service.GoodsBaseService;
import com.caocaog.market.service.GoodsHisService;
import com.caocaog.market.util.CollectionsUtil;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.CheckFailedException;
import org.jeecg.common.system.base.entity.FieldRedisItem;
import org.jeecg.common.system.base.service.impl.GenericServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品基础信息
 *
 * @author chechen
 * @date 2022-04-18
 */
@Slf4j
@Service
public class GoodsBaseServiceImpl extends GenericServiceImpl<GoodsBaseMapper, GoodsBase> implements GoodsBaseService {

    @Setter(onMethod_ = @Autowired)
    private GoodsHisService goodsHisService;
    @Setter(onMethod_ = @Autowired)
    private ShopCartDuplicateMapper shopCartDuplicateMapper;


    @Override
    public IPage<GoodsBase> queryGoodsBasePage(Page<GoodsBase> page, GoodsBase goodsBase) {
        // 去除 sorts 字段的「*」char
        final String sorts = goodsBase.getSorts();
        if (StringUtils.isNotBlank(sorts) && sorts.contains(StringPool.ASTERISK)) {
            goodsBase.setSorts(sorts.substring(1, sorts.length() - 1));
        }
        page.setOrders(ORDER_ITEM_LIST);
        return super.baseMapper.queryGoodsBasePage(page, goodsBase);
    }

    /**
     * 根据商品分类id获取商品基础信息
     *
     * @param categoriesId 商品分类id
     * @return 商品基础信息集合
     */
    @Override
    public List<GoodsBase> getShowGoodsBaseByCategoriesId(String categoriesId) {
        final String key = CacheConstant.GOODS_BASE_LIST_BY_CATEGORIES_ID + CommonConstant.DOUBLE_COLON + categoriesId;
        if (this.redisUtil.hasKey(key)) {
            return this.redisUtil.getList(key, super.entityClass);
        }
        // else
        List<GoodsBase> goodsBaseList = super.baseMapper.getGoodsBaseByCategoriesId(categoriesId)
                .stream()
                .filter(goodsBase -> "1".equals(goodsBase.getStatus()))
                // 排序规格 热门 > 排序值 > 创建时间
                .sorted(Comparator.comparing(GoodsBase::getIsHot).thenComparing(GoodsBase::getSort).thenComparing(GoodsBase::getCreateTime).reversed())
                .collect(Collectors.toList());
        this.redisUtil.set(key, goodsBaseList, CACHE_TIME_DEFAULT);
        return goodsBaseList;
    }

    /**
     * 新增商品规格信息（缓存）
     *
     * @param goodsBase 商品规格信息
     * @return 新增后的商品规格信息
     */
    @Override
    public GoodsBase insertGoodsBase(GoodsBase goodsBase) {
        super.insertCache(goodsBase);
        return super.getByIdCache(goodsBase.getId());
    }

    /**
     * 更新商品规格信息（缓存）
     *
     * @param goodsBase 商品规格信息
     * @return 更新后的商品规格信息
     */
    @Override
    public GoodsBase updateGoodsBase(GoodsBase goodsBase) {
        super.updateCache(goodsBase);
        return super.getByIdCache(goodsBase.getId());
    }

    @Override
    public String[] getGoodsIdsByCategoriesIds(String... categoriesIds) {
        return Arrays.stream(categoriesIds)
                .distinct()
                .map(categoriesId -> this.selectListByFieldCache(categoriesId, CacheConstant.GOODS_BASE_LIST_BY_CATEGORIES_ID))
                .flatMap(Collection::stream)
                .map(GoodsBase::getId)
                .toArray(String[]::new);
    }

    /**
     * 插入修改通用的数据处理
     *
     * @param goods         商品信息数据传输对象
     * @param goodsSpecDTOs 商品规格信息数据传输对象集合
     */
    public static GoodsBase dataProcess(GoodsDTO goods, List<GoodsSpecDTO> goodsSpecDTOs) {
        // 设定最低价格
        BigDecimal minPrice = BigDecimal.ZERO;
        // 转换商品现价格式
        BigDecimal price = new BigDecimal(goods.getPresentPrice());
        for (GoodsSpecDTO goodsSpec : goodsSpecDTOs) {
            // 把商品规格的价格统一保留小数点后两位，超出的向上取整
            BigDecimal specPrice = new BigDecimal(goodsSpec.getPriceSku()).setScale(2, RoundingMode.UP);
            goodsSpec.setPriceSku(specPrice.toString());
            // 商品价格如果大于等于规格价格，则把这条规格的价格赋予minPrice
            if (price.compareTo(specPrice) >= 0 || goodsSpecDTOs.size() == 1) {
                minPrice = specPrice;
            }
        }
        goods.setPresentPrice(minPrice.toString());
        if (StringUtils.isBlank(goods.getId())) {
            goods.setId(String.valueOf(new DefaultIdentifierGenerator(InetAddress.getLoopbackAddress()).nextId(null)));
        }
        if (StringUtils.isBlank(goods.getShortName())) {
            goods.setShortName(goods.getName());
        }
        if (StringUtils.isBlank(goods.getCode())) {
            goods.setCode(goods.getId());
        }
        // TODO 商家端商品描述字段替换成description可删除
        if (StringUtils.isBlank(goods.getShortDescription())) {
            goods.setShortDescription(goods.getDescription());
        }
        if (StringUtils.isBlank(goods.getDescription())) {
            goods.setDescription(goods.getShortDescription());
        }

        // 设置是否是单个规格
        return goods.toGoodsBase().setSingleSpec(goodsSpecDTOs.size() == 1);
    }

    /**
     * 获取 GOODS_LIST_BY_CATEGORIES_ID 缓存 key 值
     */
    public static String[] getGoodsListByCategoriesIdKey(GoodsBase goodsBase) {
        String[] keys;
        if (!goodsBase.getSorts().contains(StringPool.COMMA)) {
            keys = new String[]{CacheConstant.GOODS_LIST_BY_CATEGORIES_ID + CommonConstant.DOUBLE_COLON + goodsBase.getSorts()};
        } else {
            keys = Arrays.stream(goodsBase.getSorts().split(StringPool.COMMA)).map(categoriesId ->
                    CacheConstant.GOODS_LIST_BY_CATEGORIES_ID + CommonConstant.DOUBLE_COLON + categoriesId
            ).toArray(String[]::new);
        }
        return keys;
    }

    /**
     * 通用字段更改
     *
     * @param goodsBase 商品基础信息
     * @return 受影响行数
     */
    private int universalFieldChange(GoodsBase goodsBase) {
        if (Objects.isNull(goodsBase)) {
            throw new CheckFailedException("未找到相应商品基础信息");
        }
        GoodsBase updateAfterGoodsBase = this.updateGoodsBase(goodsBase);
        if (Objects.isNull(updateAfterGoodsBase)) return 0;
        this.goodsHisService.insertGoodsHis(updateAfterGoodsBase);

        // 删除 GOODS_LIST_BY_CATEGORIES_ID 缓存
        this.redisUtil.del(GoodsBaseServiceImpl.getGoodsListByCategoriesIdKey(goodsBase));

        return 1;
    }

    @Override
    public int statusChange(String id) {
        GoodsBase goodsBase = super.getByIdCache(id);
        if ("1".equals(goodsBase.getStatus())) {
            this.cleanShopCart(goodsBase.getShopId());
        }
        return this.universalFieldChange(goodsBase.reverseStatus());
    }


    @Override
    public void cleanShopCart(String shopId) {
        this.shopCartDuplicateMapper.deleteShopCartByShopId(shopId);
        String key = CacheConstant.SHOPPING_CART_LIST;
        if (StringUtils.isNotBlank(shopId)) {
            key += CommonConstant.DOUBLE_COLON + "shopId:" + shopId;
        }
        this.redisUtil.removeAll(key);
    }

    @Override
    public int isIndexChange(String id) {
        GoodsBase goodsBase = super.getByIdCache(id).reverseIndex();
        if (Objects.nonNull(goodsBase) && goodsBase.getIsIndex().equals("1")) {
            // 查询同shopId（店铺id）下，已经在首页展示的商品数量
            Integer indexCount = super.baseMapper.selectCount(new LambdaQueryWrapper<GoodsBase>()
                    .eq(GoodsBase::getShopId, goodsBase.getShopId())
                    .eq(GoodsBase::getIsIndex, "1")
            );
            if (indexCount >= 4) throw new CheckFailedException("首页最多展示4个商品");
        }
        return this.universalFieldChange(goodsBase);
    }

    @Override
    public int isHotChange(String id) {
        GoodsBase goodsBase = super.getByIdCache(id).reverseHot();
        if (Objects.nonNull(goodsBase) && goodsBase.getIsHot().equals("1")) {
            // 查询同shopId（店铺id）下，已经设置为热门的商品数量
            Integer hotCount = super.baseMapper.selectCount(new LambdaQueryWrapper<GoodsBase>()
                    .eq(GoodsBase::getShopId, goodsBase.getShopId())
                    .eq(GoodsBase::getIsHot, "1")
            );
            if (hotCount >= 100) throw new CheckFailedException("热门商品最多设置100个");
        }
        return this.universalFieldChange(goodsBase);
    }

    @Override
    public int oneNoDeliveryChange(String id) {
        return this.universalFieldChange(super.getByIdCache(id).reverseOneNoDelivery());
    }

    /**
     * 根据频道Id查询出全部的商品信息
     *
     * @param channelId 频道Id
     * @return 查询到的商品信息
     */
    @Override
    public List<GoodsBase> getAllGoodsByChannelId(String channelId) {
        List<GoodsBase> goodsBases = this.getBaseMapper().selectAllGoodsByChannelId(channelId);
        return CollectionsUtil.isEmpty(goodsBases) ? null : goodsBases;
    }

    /**
     * 固定排序字段
     */
    private static final List<OrderItem> ORDER_ITEM_LIST = Arrays.asList(
            new OrderItem("is_hot", false),
            new OrderItem("sort", false),
            new OrderItem(CommonConstant.DEFAULT_ORDER_COLUMN, false)
    );

    @Override
    public String getName() {
        return "商品基础";
    }

    @Override
    public List<FieldRedisItem<GoodsBase>> getAllFieldCacheList() {
        return Arrays.asList(
                FieldRedisItem.build(GoodsBase::getId, CacheConstant.GOODS_BASE_INFO, true),
                FieldRedisItem.build(GoodsBase::getSorts, CacheConstant.GOODS_BASE_LIST_BY_CATEGORIES_ID)
        );
    }
}
